<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>xmake</title>
  <link rel="icon" href="/assets/img/favicon.ico">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
  <meta name="description" content="Description">
  <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  <link href="/assets/npm/github-markdown/github-markdown.min.css" rel="stylesheet">
  <style>
	.markdown-body {
		box-sizing: border-box;
		min-width: 200px;
		max-width: 980px;
		margin: 0 auto;
		padding: 45px;
	}

	@media (max-width: 767px) {
		.markdown-body {
			padding: 15px;
		}
	}
  </style>
</head>
<body>
<article class="markdown-body">
<h4>This is a mirror page, please see the original page: </h4><a href="https://xmake.io/#/zh-cn/manual/xpack">https://xmake.io/#/zh-cn/manual/xpack</a>
<div id="wwads-panel" class="wwads-cn wwads-vertical wwads-sticky" data-id="239" style="max-width:180px;bottom:20px;right:20px;width:200px;height:260px;background:#fff;position:fixed"></div>
</br>
    <script type="text/javascript" charset="UTF-8" src="https://cdn.wwads.cn/js/makemoney.js" async></script>
<script async type="text/javascript" src="//cdn.carbonads.com/carbon.js?serve=CE7I52QU&placement=xmakeio" id="_carbonads_js"></script>
<style>
#carbonads {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu,
  Cantarell, "Helvetica Neue", Helvetica, Arial, sans-serif;
}

#carbonads {
  display: flex;
  max-width: 330px;
  background-color: hsl(0, 0%, 98%);
  box-shadow: 0 1px 4px 1px hsla(0, 0%, 0%, .1);
}

#carbonads a {
  color: inherit;
  text-decoration: none;
}

#carbonads a:hover {
  color: inherit;
}

#carbonads span {
  position: relative;
  display: block;
  overflow: hidden;
}

#carbonads .carbon-wrap {
  display: flex;
}

.carbon-img {
  display: block;
  margin: 0;
  line-height: 1;
}

.carbon-img img {
  display: block;
}

.carbon-text {
  font-size: 13px;
  padding: 10px;
  line-height: 1.5;
  text-align: left;
}

.carbon-poweredby {
  display: block;
  padding: 8px 10px;
  background: repeating-linear-gradient(-45deg, transparent, transparent 5px, hsla(0, 0%, 0%, .025) 5px, hsla(0, 0%, 0%, .025) 10px) hsla(203, 11%, 95%, .4);
  text-align: center;
  text-transform: uppercase;
  letter-spacing: .5px;
  font-weight: 600;
  font-size: 9px;
  line-height: 1;
}
</style>
    <h2 id="">打包接口</h2>
<p>xpack 作为插件形式提供，它的所有 API 我们需要通过 <code>includes("@builtin/xpack")</code> 方式来引入。</p>
<pre><code class="lang-lua">includes("@builtin/xpack")

xpack("test")
    set_version("1.0")
    set_homepage("https://xmake.io")
    add_installfiles("...")
</code></pre>
<h3 id="xpackset_version">xpack:set_version</h3>
<h4 id="">设置包版本</h4>
<p>这个接口用于设置生成的安装包的版本：</p>
<pre><code class="lang-lua">xpack("test")
    set_version("1.0")
    -- ...
</code></pre>
<p>如果我们没有设置，但是通过 <code>set_targets</code> 绑定了安装的目标程序，那么也会使用 target 中的版本配置。</p>
<pre><code class="lang-lua">target("foo")
    set_version("1.0")

xpack("test")
    set_targets("foo")
    -- ...
</code></pre>
<p>我们也可以使用全局工程的版本，如果没有绑定任何 targets。</p>
<pre><code class="lang-lua">set_version("1.0")

xpack("xmake")
    -- ...
</code></pre>
<h3 id="xpackset_homepage">xpack:set_homepage</h3>
<h4 id="">设置主页信息</h4>
<pre><code class="lang-lua">xpack("xmake")
    set_homepage("https://xmake.io")
</code></pre>
<h3 id="xpackset_title">xpack:set_title</h3>
<h4 id="">设置标题信息</h4>
<p>通常用于配置安装包的简单描述，相比 <code>set_description</code> 更加简短。</p>
<pre><code class="lang-lua">xpack("xmake")
    set_title("Xmake build utility ($(arch))")
</code></pre>
<h3 id="xpackset_description">xpack:set_description</h3>
<h4 id="">设置详细描述</h4>
<p>这个接口可以设置安装包更加详细的描述信息，可以用一到两句话详细描述下包。</p>
<pre><code class="lang-lua">xpack("xmake")
    set_description("A cross-platform build utility based on Lua.")
</code></pre>
<h3 id="xpackset_author">xpack:set_author</h3>
<h4 id="">设置作者信息</h4>
<p>我们可以设置邮箱，姓名等来描述这个包的作者。</p>
<pre><code class="lang-lua">xpack("xmake")
    set_author("waruqi@gmail.com")
</code></pre>
<h3 id="xpackset_maintainer">xpack:set_maintainer</h3>
<h4 id="">设置维护者信息</h4>
<p>我们可以设置邮箱，姓名等来描述这个包的维护者。</p>
<p>维护者跟作者有可能是同一个人，也可能不是一个人。</p>
<pre><code class="lang-lua">xpack("xmake")
    set_maintainer("waruqi@gmail.com")
</code></pre>
<h3 id="xpackset_copyright">xpack:set_copyright</h3>
<h4 id="">设置包的版权信息</h4>
<pre><code class="lang-lua">xpack("xmake")
    set_copyright("Copyright (C) 2015-present, TBOOX Open Source Group")
</code></pre>
<h3 id="xpackset_license">xpack:set_license</h3>
<h4 id="license">设置包的 License</h4>
<p>目前像 srpm/rpm/deb 等包会用到，用于设置 License 名。</p>
<pre><code class="lang-lua">set_license("Apache-2.0")
</code></pre>
<h3 id="xpackset_licensefile">xpack:set_licensefile</h3>
<h4 id="license">设置包的 License 文件</h4>
<p>我们可以设置 LICENSE 所在的文件路径，像 NSIS 的安装包，它还会额外将 LICENSE 页面展示给安装用户。</p>
<pre><code class="lang-lua">xpack("xmake")
    set_licensefile("../LICENSE.md")
</code></pre>
<h3 id="xpackset_company">xpack:set_company</h3>
<h4 id="">设置包所属的公司</h4>
<p>我们可以用这个接口设置包所属的公司和组织名。</p>
<pre><code class="lang-lua">xpack("xmake")
    set_company("tboox.org")
</code></pre>
<h3 id="xpackset_inputkind">xpack:set_inputkind</h3>
<h4 id="">设置打包的输入源类型</h4>
<p>这是个可选接口，可用于标识当前打包的输入源类型</p>
<ul>
<li>binary: 从二进制文件作为输入源打包，通常使用 <code>add_installfiles</code></li>
<li>source: 从源文件作为输入源开始打包，通常使用 <code>add_sourcefiles</code></li>
</ul>
<p>这一般用于自定义的打包格式，而对于内置的格式，比如: nsis, zip, srczip 等等，<br>其实已经能够判断获取到当前打包的输入源是从源码开始打包，还是直接从二进制源开始打包。</p>
<p>因此，除非必要（比如要自定义打包格式），通常我们不需要设置它。</p>
<p>而我们在脚本域中，也可以通过 <code>package:from_source()</code> 和 <code>package:from_binary()</code> 来判断当前的输入源。</p>
<pre><code class="lang-lua">xpack("test")
    set_formats("nsis", "zip", "targz", "srczip", "srctargz", "runself")
    add_installfiles("src/(assets/*.png)", {prefixdir = "images"})
    add_sourcefiles("(src/**)")
    on_load(function (package)
        if package:from_source() then
            package:set("basename", "test-$(plat)-src-v$(version)")
        else
            package:set("basename", "test-$(plat)-$(arch)-v$(version)")
        end
    end)
</code></pre>
<p>如果上面的打包配置，如果是 nsis 包，默认从二进制文件作为输入源，进行打包，会去打包 <code>add_installfiles</code> 配置的文件。</p>
<p>而 <code>srczip</code>, <code>srctargz</code> 和 <code>runself</code> 是从源文件开始打包，会去打包 <code>add_sourcefiles</code> 中的文件，然后再执行打包脚本。</p>
<h3 id="xpackset_formats">xpack:set_formats</h3>
<h4 id="">设置打包格式</h4>
<p>配置当前 XPack 包需要生成的打包格式，可以同时配置多个，<code>xmake pack</code> 命令会一次性全部生成。</p>
<p>!> 有些格式如果当前平台不支持生成，会自动忽略。</p>
<pre><code class="lang-lua">xpack("test")
    set_formats("nsis", "zip", "targz", "srczip", "srctargz", "runself")
</code></pre>
<p>我们也可以通过命令，指定生成其中部分格式，而不是一次性全部生成。</p>
<pre><code class="lang-bash">$ xmake pack -f "nsis,zip"
</code></pre>
<p>通过逗号分隔，指定生成 NSIS 和 zip 包，暂时忽略其他格式包。</p>
<p>目前支持的格式有：</p>
<table>
<thead>
<tr>
<th>格式</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td>nsis</td>
<td>Windows NSIS 安装包，二进制安装</td>
</tr>
<tr>
<td>zip</td>
<td>二进制 zip 包，不包含安装脚本</td>
</tr>
<tr>
<td>targz</td>
<td>二进制 tar.gz 包，不包含安装脚本</td>
</tr>
<tr>
<td>srczip</td>
<td>zip 源码包</td>
</tr>
<tr>
<td>srctargz</td>
<td>tar.gz 源码包</td>
</tr>
<tr>
<td>runself</td>
<td>自运行 shell 脚本包，源码编译安装</td>
</tr>
<tr>
<td>rpm</td>
<td>rpm 二进制安装包</td>
</tr>
<tr>
<td>srpm</td>
<td>rpm 源码安装包</td>
</tr>
<tr>
<td>deb</td>
<td>deb 二进制安装包 （待支持）</td>
</tr>
<tr>
<td>其他</td>
<td>可自定义格式和安装脚本</td>
</tr>
</tbody>
</table>
<h3 id="xpackset_basename">xpack:set_basename</h3>
<h4 id="">设置包文件名</h4>
<p>设置生成包的文件名，但不包含后缀名。</p>
<pre><code class="lang-lua">xpack("xmake")
    set_basename("xmake-v$(version)")
</code></pre>
<p>我们也可以在其中配置 <code>$(version)</code>, <code>$(plat)</code>, <code>$(arch)</code> 等变量。</p>
<p>另外，想要更灵活的配置，可以再 on_load 脚本中去配置它。</p>
<pre><code class="lang-lua">xpack("xmake")
    on_load(function (package)
        package:set("basename", "xmake-v" .. package:version())
    end)
</code></pre>
<h3 id="xpackset_extension">xpack:set_extension</h3>
<h4 id="">设置安装包的扩展名</h4>
<p>通常我们并不需要修改生成包的扩展名，因为指定了 <code>nsis</code>, <code>zip</code> 等格式后，都会有一个默认的后缀名，例如：<code>.exe</code>, <code>.zip</code>。</p>
<p>但是，如果我们正在自定义包格式，需要生成一个自定义的包，那么我们可能需要配置它。</p>
<pre><code class="lang-lua">xpack("mypack")
    set_format("myformat")
    set_extension(".myf")
    on_package(function (package)
        local outputfile = package:outputfile()
        -- TODO
    end)
</code></pre>
<p>例如，这里我们自定义了一个 myformat 包格式，采用 <code>.myf</code> 的自定义后缀名，然后我们就可以在 on_package 中生成它，</p>
<p><code>package:outputfile()</code> 返回的包输出文件名中就会包含这个后缀名。</p>
<h3 id="xpackadd_targets">xpack:add_targets</h3>
<h4 id="">关联目标程序</h4>
<p>我们可以通过这个接口，配置关联需要被安装的目标 target。</p>
<pre><code class="lang-lua">target("foo")
    set_kind("shared")
    add_files("src/*.cpp")
    add_headerfiles("include/(*.h)")

xpack("test")
    set_formats("nsis")
    add_targets("foo")
</code></pre>
<p>当生成 test 安装包的时候，被关联的 foo 目标的可执行程序，动态库等待都会被一起打包安装。<br>另外，target 中通过 <code>add_headerfiles</code> 和 <code>add_installfiles</code> 配置的自定义安装文件也会被打入安装包，一起被安装。</p>
<p>而且我们还可以在 target 和它的 rules 中通过 <code>on_installcmd</code>, <code>after_installcmd</code> 等自定义打包安装脚本，也会被一起执行。</p>
<h3 id="xpackadd_components">xpack:add_components</h3>
<h4 id="">添加安装包组件</h4>
<p>我们也支持为安装包添加自定义组件，按组件模式进行选择安装。目前仅仅对 NSIS 包会有比较的支持效果。</p>
<p>我们可以通过 <code>xpack_component()</code> 定义一个组件域，然后使用 <code>add_components()</code> 加指定的组件跟包进行关联绑定。</p>
<p>而在组件中，我们可以通过 <code>on_installcmd()</code> 编写一些自定义的安装脚本，只有当这个组件被启用的情况下，才会被执行安装。</p>
<pre><code class="lang-lua">xpack("test")
    add_components("LongPath")

xpack_component("LongPath")
    set_default(false)
    set_title("Enable Long Path")
    set_description("Increases the maximum path length limit, up to 32,767 characters (before 256).")
    on_installcmd(function (component, batchcmds)
        batchcmds:rawcmd("nsis", [[
  ${If} $NoAdmin == "false"
    ; Enable long path
    WriteRegDWORD ${HKLM} "SYSTEM\CurrentControlSet\Control\FileSystem" "LongPathsEnabled" 1
  ${EndIf}]])
    end)
</code></pre>
<p>这里，我们使用 <code>batchcmds:rawcmd("nsis", "...")</code> 添加了一个 nsis 特有的安装命令，开启长路径支持。效果如下：</p>
<p><img src="/assets/img/manual/nsis_4.png" alt=""></p>
<p>只有当我们勾选 LongPath 后，才会启用，当然，我们也可以通过 <code>set_default()</code> 配置组件默认是否处于启用状态。</p>
<p>除了 NSIS 包，其他包尽管没有对组件有完善的支持，但是同样会执行组件里面的脚本实现打包，仅仅可能无法显示对应的组件 UI 和勾选框。</p>
<h3 id="xpackset_bindir">xpack:set_bindir</h3>
<h4 id="">设置包的二进制安装目录</h4>
<p>通常生成的安装包都会有一个安装根目录，而我们可以通过这个配置指定安装目录下的 bin 目录位置。</p>
<p>如果没有指定，默认在 <code>installdir/bin</code>。</p>
<p>如果配置了</p>
<pre><code class="lang-lua">xpack("xmake")
    set_bindir("mybin")
</code></pre>
<p>那么会将可执行文件安装在 <code>installdir/mybin</code> 下面，如果是 NSIS 包，安装后，还会自动设置此路径到 <code>%PATH%</code>。</p>
<h3 id="xpackset_libdir">xpack:set_libdir</h3>
<h4 id="">设置包的库安装目录</h4>
<p>通常生成的安装包都会有一个安装根目录，而我们可以通过这个配置指定安装目录下的 lib 目录位置。</p>
<p>如果没有指定，默认在 <code>installdir/lib</code>。</p>
<p>如果配置了</p>
<pre><code class="lang-lua">xpack("xmake")
    set_libdir("mylib")
</code></pre>
<p>那么会将静态库文件安装在 <code>installdir/mylib</code> 下面。</p>
<h3 id="xpackset_includedir">xpack:set_includedir</h3>
<h4 id="">设置包的头文件安装目录</h4>
<p>通常生成的安装包都会有一个安装根目录，而我们可以通过这个配置指定安装目录下的 include 目录位置。</p>
<p>如果没有指定，默认在 <code>installdir/include</code>。</p>
<p>如果配置了</p>
<pre><code class="lang-lua">xpack("xmake")
    set_includedir("myinc")
</code></pre>
<p>那么会将头文件安装在 <code>installdir/myinc</code> 下面。</p>
<h3 id="xpackset_prefixdir">xpack:set_prefixdir</h3>
<h4 id="">设置包的安装前缀目录</h4>
<p>如果配置了</p>
<pre><code class="lang-lua">xpack("xmake")
    set_prefixdir("prefix")
</code></pre>
<p>那么会将所有安装文件，安装在 <code>installdir/prefix</code> 下面，例如：</p>
<pre><code>installdir
  - prefix
    - include
    - lib
    - bin
</code></pre><h3 id="xpackset_specfile">xpack:set_specfile</h3>
<h4 id="spec">设置包 spec 文件路径</h4>
<p>有些包格式的生成，需要先生成特定的 spec 文件，然后才能调用第三方打包工具去生成包。</p>
<p>比如 NSIS 包，需要先通过 xmake 根据 xpack 配置，生成 NSIS 特有的 <code>.nsi</code> 配置文件，然后 xmake 会再调用 <code>makensis.exe</code> 去根据这个 <code>.nsi</code> 文件生成 NSIS 包。</p>
<p>而 deb/rpm 等包都有特定的 spec 文件。</p>
<p>xmake 在打包的时候，默认会自动生成一个 spec 文件，但是如果我们想更加深度定制化一些特有包的配置，可以通过这个接口，</p>
<p>配置一个自己的 spec 文件，里面用户自己维护了一些包配置定义，然后可以在里面定义一些 <code>${PACKAGE_NAME}</code>, <code>${VERSION}</code> 包特有的内置变量，就可以实现包信息替换。</p>
<pre><code class="lang-lua">xpack("xmake")
    set_formats("nsis")
    set_specfile("makensis.nsi")
</code></pre>
<p>makensis.nsi</p>
<pre><code>VIProductVersion                         "${VERSION}.0"
VIFileVersion                            "${VERSION}.0"
VIAddVersionKey /LANG=0 ProductName      "${PACKAGE_NAME}"
VIAddVersionKey /LANG=0 Comments         "${PACKAGE_DESCRIPTION}"
VIAddVersionKey /LANG=0 CompanyName      "${PACKAGE_COMPANY}"
VIAddVersionKey /LANG=0 LegalCopyright   "${PACKAGE_COPYRIGHT}"
VIAddVersionKey /LANG=0 FileDescription  "${PACKAGE_NAME} Installer - v${VERSION}"
VIAddVersionKey /LANG=0 OriginalFilename "${PACKAGE_FILENAME}"
</code></pre><p>下面是一些内置的常用包变量：</p>
<table>
<thead>
<tr>
<th>变量名</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>PACKAGE_ARCH</td>
<td>包二进制文件的架构</td>
</tr>
<tr>
<td>PACKAGE_PLAT</td>
<td>包二进制文件的平台</td>
</tr>
<tr>
<td>PACKAGE_NAME</td>
<td>包名</td>
</tr>
<tr>
<td>PACKAGE_TITLE</td>
<td>包的简单描述</td>
</tr>
<tr>
<td>PACKAGE_DESCRIPTION</td>
<td>包的详细描述</td>
</tr>
<tr>
<td>PACKAGE_FILENAME</td>
<td>包文件名</td>
</tr>
<tr>
<td>PACKAGE_AUTHOR</td>
<td>包作者</td>
</tr>
<tr>
<td>PACKAGE_MAINTAINER</td>
<td>包维护者</td>
</tr>
<tr>
<td>PACKAGE_HOMEPAGE</td>
<td>包主页地址</td>
</tr>
<tr>
<td>PACKAGE_COPYRIGHT</td>
<td>包的版权信息</td>
</tr>
<tr>
<td>PACKAGE_COMPANY</td>
<td>包所属的公司名</td>
</tr>
<tr>
<td>PACKAGE_ICONFILE</td>
<td>包的图标文件路劲</td>
</tr>
<tr>
<td>PACKAGE_LICENSEFILE</td>
<td>包的 LICENSE 文件路径</td>
</tr>
<tr>
<td>PACKAGE_VERSION_MAJOR</td>
<td>包的 major 版本</td>
</tr>
<tr>
<td>PACKAGE_VERSION_MINOR</td>
<td>包的 minor 版本</td>
</tr>
<tr>
<td>PACKAGE_VERSION_ALTER</td>
<td>包的 alter 版本</td>
</tr>
<tr>
<td>PACKAGE_VERSION_BUILD</td>
<td>包的 build 版本</td>
</tr>
</tbody>
</table>
<p>除了内置变量，我们也可以通过 <code>set_specvar</code> 接口去配置一些自定义的模版变量。</p>
<h3 id="xpackset_specvar">xpack:set_specvar</h3>
<h4 id="spec">设置包 spec 文件的自定义变量</h4>
<p>通常配合 <code>set_specfile</code> 接口一起使用，用于在自定义的 spec 模版文件里面，设置一些自定义的包变量。</p>
<pre><code class="lang-lua">xpack("xmake")
    set_formats("nsis")
    set_specfile("makensis.nsi")
    set_specvar("FOO", "hello")
</code></pre>
<p>makensis.nsi</p>
<pre><code>VIAddVersionKey /LANG=0 ProductName      "${FOO}"
</code></pre><p>在生成包之前，xmake 会替换 <code>${FOO}</code> 成 hello，然后再调用 <code>makensis.exe</code> 命令根据这个文件生成 NSIS 安装包。</p>
<h3 id="xpackset_iconfile">xpack:set_iconfile</h3>
<h4 id="">设置图标文件路径</h4>
<p>我们可以额外配置一个 ico 的图标文件，可以用于设置 NSIS 等一些支持图标自定义的安装包的图标。</p>
<pre><code class="lang-lua">xpack("xmake")
    set_iconfile("xmake.ico")
</code></pre>
<h3 id="xpackadd_sourcefiles">xpack:add_sourcefiles</h3>
<h4 id="">添加源文件</h4>
<p>这通常用于源码包，也就是 <code>srczip</code>, <code>srctargz</code> 这种纯源码包，以及 <code>runself</code> 格式的源码安装包。</p>
<p>如果是自定义的包格式，我们需要配置 <code>set_inputkind("source")</code> 开启源码包。</p>
<p>通过这个接口，可以自定义配置那些源文件需要被打入包中，用于后期的编译安装。</p>
<p>它的详细用法跟 <code>add_installfiles</code> 类似，可以参考它的文档描述。</p>
<h3 id="xpackadd_installfiles">xpack:add_installfiles</h3>
<h4 id="">添加二进制文件</h4>
<p>这通常用于二进制包，也就是 <code>nsis</code>, <code>deb</code> 等格式的包，这些包会直接安装二进制文件。</p>
<p>因此，我们可以通过这个接口额外配置一些需要被安装的二进制文件，比如：可执行文件，资源文件等等。</p>
<p>比如我们可以指定安装各种类型的文件到安装目录：</p>
<pre><code class="lang-lua">xpack("test")
    add_installfiles("src/*.h")
    add_installfiles("doc/*.md")
</code></pre>
<p>我们也可以指定安装到特定子目录：</p>
<pre><code class="lang-lua">xpack("test")
    add_installfiles("src/*.h", {prefixdir = "include"})
    add_installfiles("doc/*.md", {prefixdir = "share/doc"})
</code></pre>
<p>上面的设置，我们会安装到<code>installdir/include/*.h</code>, <code>installdir/share/doc/*.md</code>。</p>
<p>注：默认安装不会保留目录结构，会完全展开，当然我们也可以通过<code>()</code>去提取源文件中的子目录结构来安装，例如：</p>
<pre><code class="lang-lua">xpack("test")
    add_installfiles("src/(tbox/*.h)", {prefixdir = "include"})
    add_installfiles("doc/(tbox/*.md)", {prefixdir = "share/doc"})
</code></pre>
<h3 id="xpackadd_buildrequires">xpack:add_buildrequires</h3>
<h4 id="">添加包的构建依赖</h4>
<p>这通常用于一些源码包，例如 srpm。这些源码包在安装之前，需要先构建源码，而构建源码可能会需要用到一些其他的依赖包。</p>
<p>我们可以通过这个接口去配置它们。</p>
<pre><code class="lang-lua">xpack("test")
    set_formats("srpm")
    on_load(function (package)
        local format = package:format()
        if format == "srpm" then
            package:add("buildrequires", "make")
            package:add("buildrequires", "gcc")
            package:add("buildrequires", "gcc-c++")
        end
    end)
    on_buildcmd(function (package, batchcmds)
        batchcmds:runv("make")
    end)
</code></pre>
<p>由于不同的安装包，它的依赖包名会有一些差异，所以我们需要在 on_load 脚本域针对不同的包格式，去配置它们。</p>
<h3 id="xpackon_load">xpack:on_load</h3>
<h4 id="">自定义加载脚本</h4>
<p>如果在描述域中配置无法满足我们的需求，还可以在 on_load 自定义脚本域中，进一步灵活的配置包。</p>
<p>这个接口会在每个 XPack 包初始化加载期间就被调用，可以在里面做一些基础配置。</p>
<p>例如在里面动态地修改包文件名：</p>
<pre><code class="lang-lua">xpack("test")
    on_load(function (package)
        package:set("basename", "test-" .. package:version())
    end)
</code></pre>
<h3 id="xpackbefore_package">xpack:before_package</h3>
<h4 id="">自定义打包之前的脚本</h4>
<p>我们可以通过这个接口配置打包之前的自定义脚本。</p>
<pre><code class="lang-lua">xpack("test")
    before_package(function (package)
        -- TODO
    end)
</code></pre>
<h3 id="xpackon_package">xpack:on_package</h3>
<h4 id="">自定义打包脚本</h4>
<p>我们可以通过这个接口配置打包自定义脚本，这将会重写整个内置的打包逻辑。通常用于自定义包格式。</p>
<pre><code class="lang-lua">xpack("test")
    set_formats("xxx")
    on_package(function (package)
        -- TODO
    end)
</code></pre>
<h3 id="xpackafter_package">xpack:after_package</h3>
<h4 id="">自定义打包之后的脚本</h4>
<p>我们可以通过这个接口配置打包之后的自定义脚本。</p>
<pre><code class="lang-lua">xpack("test")
    after_package(function (package)
        -- TODO
    end)
</code></pre>
<h3 id="xpackbefore_installcmd">xpack:before_installcmd</h3>
<h4 id="">添加安装之前的脚本</h4>
<p>它不会重写整个安装脚本，但是会在现有的安装脚本执行之前，新增一些自定义的安装脚本：</p>
<pre><code class="lang-lua">xpack("test")
    before_installcmd(function (package, batchcmds)
        batchcmds:mkdir(package:installdir("resources"))
        batchcmds:cp("src/assets/*.txt", package:installdir("resources"), {rootdir = "src"})
        batchcmds:mkdir(package:installdir("stub"))
    end)
</code></pre>
<p>需要注意的是，通过 <code>batchcmds</code> 添加的 cp, mkdir 等命令都不会被立即执行，而是仅仅生成一个命令列表，后面实际生成包的时候，会将这些命令，翻译成打包命令。</p>
<h3 id="xpackon_buildcmd">xpack:on_buildcmd</h3>
<h4 id="">自定义构建脚本</h4>
<p>对于一些源码构建包，在安装之前，我们需要先构建源码，例如 srpm 包。</p>
<p>因此，我们可以通过这个接口，自定义构建脚本，例如：</p>
<pre><code class="lang-lua">xpack("test")
    set_formats("srpm")
    add_sourcefiles("src/*.c")
    add_sourcefiles("./configure")
    on_buildcmd(function (package, batchcmds)
        batchcmds:runv("./configure")
        batchcmds:runv("make")
    end)
</code></pre>
<p>如果我们通过 add_targets 关联了目标程序，即使我们没有配置 <code>on_buildcmd</code>，xpack 也会默认执行 <code>xmake build</code> 命令去构建它们。</p>
<pre><code class="lang-lua">xpack("test")
    set_formats("srpm")
    add_sourcefiles("src/*.c")
    add_sourcefiles("./xmake.lua")
</code></pre>
<p>另外，我们也可以使用 <code>add_buildrequires</code> 去配置一些构建依赖。</p>
<h3 id="xpackbefore_buildcmd">xpack:before_buildcmd</h3>
<h4 id="">自定义构建之前的脚本</h4>
<p>通过这个接口，我们可以配置构建之前的脚本。</p>
<pre><code class="lang-lua">xpack("test")
    set_formats("srpm")
    before_buildcmd(function (package, batchcmds)
        -- TODO
    end)
</code></pre>
<h3 id="xpackafter_buildcmd">xpack:after_buildcmd</h3>
<h4 id="">自定义构建之后的脚本</h4>
<p>通过这个接口，我们可以配置构建之后的脚本。</p>
<pre><code class="lang-lua">xpack("test")
    set_formats("srpm")
    after_buildcmd(function (package, batchcmds)
        -- TODO
    end)
</code></pre>
<h3 id="xpackon_installcmd">xpack:on_installcmd</h3>
<h4 id="">自定义安装脚本</h4>
<p>这回完全重写内置默认的安装脚本，包括内部对 <code>add_installfiles</code> 配置的文件的自动安装，用户需要完全自己处理所有的安装逻辑。</p>
<h3 id="xpackafter_installcmd">xpack:after_installcmd</h3>
<h4 id="">添加安装之后的脚本</h4>
<p>它不会重写整个安装脚本，但是会在现有的安装脚本执行之后，新增一些自定义的安装脚本：</p>
<pre><code class="lang-lua">xpack("test")
    after_installcmd(function (package, batchcmds)
        batchcmds:mkdir(package:installdir("resources"))
        batchcmds:cp("src/assets/*.txt", package:installdir("resources"), {rootdir = "src"})
        batchcmds:mkdir(package:installdir("stub"))
    end)
</code></pre>
<p>需要注意的是，通过 <code>batchcmds</code> 添加的 cp, mkdir 等命令都不会被立即执行，而是仅仅生成一个命令列表，后面实际生成包的时候，会将这些命令，翻译成打包命令。</p>
<h3 id="xpackbefore_uninstallcmd">xpack:before_uninstallcmd</h3>
<h4 id="">添加卸载之前的脚本</h4>
<p>跟 before_installcmd 类似，请参考 before_installcmd 说明。</p>
<h3 id="xpackon_uninstallcmd">xpack:on_uninstallcmd</h3>
<h4 id="">自定义卸载脚本</h4>
<p>跟 on_installcmd 类似，请参考 on_installcmd 说明。</p>
<h3 id="xpackafter_uninstallcmd">xpack:after_uninstallcmd</h3>
<h4 id="">添加卸载之后的脚本</h4>
<p>跟 after_installcmd 类似，请参考 after_installcmd 说明。</p>
<h3 id="xpackset_nsis_displayicon">xpack:set_nsis_displayicon</h3>
<h4 id="nsis">设置 NSIS 的显示图标</h4>
<p>这是一个 NSIS 专有 API，可以用于配置 NSIS 的显示图标：</p>
<pre><code class="lang-lua">xpack("test")
    set_nsis_displayicon("bin/foo.exe")
</code></pre>
<p>我们需要配置带有 icon 的可执行文件路径，这是使得安装包的显示 icon 跟它保持一致。</p>
<p>这是一个可选配置，即使我们不配置它，xmake 也会默认使用被关联的 target 中的可执行文件中图标。</p>
<h2 id="">组件接口</h2>
<h3 id="xpack_componentset_title">xpack_component:set_title</h3>
<h4 id="">设置包组件的简单描述</h4>
<pre><code class="lang-lua">xpack_component("LongPath")
    set_title("Enable Long Path")
</code></pre>
<h3 id="xpack_componentset_description">xpack_component:set_description</h3>
<h4 id="">设置包组件的详细描述</h4>
<pre><code class="lang-lua">xpack_component("LongPath")
    set_description("Increases the maximum path length limit, up to 32,767 characters (before 256).")
</code></pre>
<h3 id="xpack_componentset_default">xpack_component:set_default</h3>
<h4 id="">设置包组件的默认启用状态</h4>
<p>通常包组件都会被默认启用，但是我们也可以使用这个接口，默认禁用这个组件，仅仅当用户安装包时候，选择勾选此组件，才会被启用安装。</p>
<pre><code class="lang-lua">xpack_component("LongPath")
    set_default(false)
    set_title("Enable Long Path")
</code></pre>
<h3 id="xpack_componenton_load">xpack_component:on_load</h3>
<h4 id="">自定义加载脚本</h4>
<p>我们可以在 on_load 自定义脚本域中，进一步灵活的配置包组件。</p>
<pre><code class="lang-lua">xpack_component("test")
    on_load(function (component)
        local package = component:package()
        -- TODO
    end)
</code></pre>
<h3 id="xpack_componentbefore_installcmd">xpack_component:before_installcmd</h3>
<h4 id="">添加组件安装之前的脚本</h4>
<p>它不会重写整个安装脚本，但是会在现有的安装脚本执行之前，新增一些自定义的安装脚本：</p>
<pre><code class="lang-lua">xpack_component("test")
    before_installcmd(function (component, batchcmds)
        batchcmds:mkdir(package:installdir("resources"))
        batchcmds:cp("src/assets/*.txt", package:installdir("resources"), {rootdir = "src"})
        batchcmds:mkdir(package:installdir("stub"))
    end)
</code></pre>
<p>需要注意的是，通过 <code>batchcmds</code> 添加的 cp, mkdir 等命令都不会被立即执行，而是仅仅生成一个命令列表，后面实际生成包的时候，会将这些命令，翻译成打包命令。</p>
<p>它跟 xpack 的 before_installcmd 使用是完全一样的，唯一的区别是，仅仅当这个组件被启用时候，才会执行这里的安装脚本。</p>
<h3 id="xpack_componenton_installcmd">xpack_component:on_installcmd</h3>
<h4 id="">重写组件的安装脚本</h4>
<p>这会重写整个组件的安装脚本，类似 xpack 的 on_installcmd。</p>
<pre><code class="lang-lua">xpack_component("test")
    on_installcmd(function (component, batchcmds)
        -- TODO
    end)
</code></pre>
<h3 id="xpack_componentafter_installcmd">xpack_component:after_installcmd</h3>
<h4 id="">添加组件安装之后的脚本</h4>
<p>在组件安装之后，会执行这里的脚本，类似 xpack 的 after_installcmd。</p>
<pre><code class="lang-lua">xpack_component("test")
    after_installcmd(function (component, batchcmds)
        -- TODO
    end)
</code></pre>
<h3 id="xpack_componentbefore_uninstallcmd">xpack_component:before_uninstallcmd</h3>
<h4 id="">添加组件卸载之前的脚本</h4>
<p>在组件安装之后，会执行这里的脚本，类似 xpack 的 before_uninstallcmd。</p>
<pre><code class="lang-lua">xpack_component("test")
    before_uninstallcmd(function (component, batchcmds)
        -- TODO
    end)
</code></pre>
<h3 id="xpack_componenton_uninstallcmd">xpack_component:on_uninstallcmd</h3>
<h4 id="">重写组件卸载的脚本</h4>
<p>这会重写整个组件的卸载脚本，类似 xpack 的 on_uninstallcmd。</p>
<pre><code class="lang-lua">xpack_component("test")
    on_uninstallcmd(function (component, batchcmds)
        -- TODO
    end)
</code></pre>
<h3 id="xpack_componentafter_uninstallcmd">xpack_component:after_uninstallcmd</h3>
<h4 id="">添加组件卸载之后的脚本</h4>
<p>在组件卸载之后，会执行这里的脚本，类似 xpack 的 before_uninstallcmd。</p>
<pre><code class="lang-lua">xpack_component("test")
    before_uninstallcmd(function (component, batchcmds)
        -- TODO
    end)
</code></pre>
<h3 id="xpack_componentadd_sourcefiles">xpack_component:add_sourcefiles</h3>
<h4 id="">添加组件源文件</h4>
<p>这类似于 xpack 的 add_sourcefiles，但这里仅仅当组件被启用后，才会将这些源文件打入安装包。</p>
<h3 id="xpack_componentadd_installfiles">xpack_component:add_installfiles</h3>
<h4 id="">添加组件二进制安装文件</h4>
<p>这类似于 xpack 的 add_installfiles，但这里仅仅当组件被启用后，才会将这些二进制文件打入安装包。</p>
</article>
</body>
</html>